home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / tutorials / custEducation / opengl2 / demos / lens.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  28.7 KB  |  1,144 lines

  1. /*
  2.  * Copyright (c) 1994 Silicon Graphics, Inc.
  3.  * 
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee,
  6.  * provided that (i) the above copyright notices and this permission
  7.  * notice appear in all copies of the software and related documentation,
  8.  * and (ii) the name of Silicon Graphics may not be used in any
  9.  * advertising or publicity relating to the software without the specific,
  10.  * prior written permission of Silicon Graphics.
  11.  * 
  12.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  13.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  14.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  15.  * 
  16.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL,
  17.  * INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
  18.  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  19.  * OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
  20.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  21.  * OF THIS SOFTWARE.
  22.  */
  23.  
  24. /*
  25.  *  lens - Roam around a very large image using textures tiles.
  26.  *
  27.  *  Demonstrates the use of subtexture and texture color table extensions.
  28.  *
  29.  *  $Revision: 1.1 $
  30.  */
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <bstring.h>
  35. #include <math.h>
  36. #include <GL/glu.h>
  37. #include <GL/gl.h>
  38. #include <GL/glx.h>
  39. #include <X11/keysym.h>
  40. #include <gl/image.h>
  41. #include "xwindow.h"
  42. #include "util.h"
  43.  
  44. #if !defined(GL_EXT_subtexture) || !defined(GL_EXT_abgr)
  45. BOTH EXT_subtexture and EXT_abgr must be defined
  46. #else
  47.  
  48.  
  49. /* set to 1 for debug.. slower, but includes error checking */
  50. #define DEBUG 0
  51.  
  52. /* a word the size of 4 bytes (e.g. an RGBA pixel) */
  53. typedef unsigned int u_int32;
  54.  
  55. typedef struct tileimg {
  56.     int xsize, ysize;
  57.     int xtiles, ytiles;
  58.     int tilexsize, tileysize;
  59.     u_int32 **tiles;
  60. } tileimg; 
  61.  
  62. tileimg *img = NULL;
  63.  
  64. #define GETTILE(IMG,TX,TY) ((IMG)->tiles[(TY)*(IMG)->xtiles+(TX)])
  65.  
  66. #define MAXWIDTH    (4*4096)
  67.  
  68. /* size of the physical texture */
  69. #define  TEX_SIZE_S   1024
  70. #define  TEX_SIZE_T   1024
  71.  
  72. int Lminx = -TEX_SIZE_S; 
  73. int Lmaxx = -TEX_SIZE_S; 
  74. int Lminy = -TEX_SIZE_T;
  75. int Lmaxy = -TEX_SIZE_T;
  76.  
  77. unsigned int    tileXSize = 64;
  78. unsigned int    tileYSize = 64;
  79.  
  80. long winxsize, winysize;
  81. int xorg, yorg;
  82.  
  83. float myangle = 0;
  84. float zoom = 1;
  85. GLboolean useTct;
  86.  
  87. u_int32 *bgdtile = NULL;
  88. Display *dpy;
  89. Window win;
  90.  
  91. tileimg *readTiles();
  92. void changeTct(void);
  93. void changeModel(void);
  94. void rgbToPackedRgba(unsigned short *rbuf, unsigned short *gbuf,
  95.                      unsigned short *bbuf, u_int32 *lbuf,int xsize);
  96. void processEvents(void);
  97. void makeMesh0(float x0, float x1, float y0, float y1,
  98.                float s0, float s1, float t0, float t1, float z, int nx,int ny);
  99. void makeMesh1(float x0, float x1, float y0, float y1,
  100.                float s0, float s1, float t0, float t1, float z, int nx,int ny);
  101. void makeMesh2(float x0, float x1, float y0, float y1,
  102.                float s0, float s1, float t0, float t1, float z, int nx,int ny);
  103. void makeMesh3(float x0, float x1, float y0, float y1,
  104.                float s0, float s1, float t0, float t1, float z, int nx,int ny);
  105. void makeTable1(void);
  106. void makeTable2(void);
  107. void makeTable3(void);
  108. void makeTable4(void);
  109.  
  110. void drawTiles(tileimg *img, int xorg, int yorg, int winxsize, int winysize);
  111. void makeRgbBgdTile(void);
  112. void makeRgbaBgdTile(void);
  113. void applyRgbaBgd(tileimg *img);
  114. tileimg *readTiles(IMAGE *image, int tilexsize, int tileysize);
  115.  
  116. #if DEBUG
  117. void chkError(char *msg);
  118. #else
  119. #define chkError
  120. #endif
  121. void usage(char *name, int exitStatus);
  122.  
  123. void
  124. printHelp(void)
  125. {
  126.     printf("\tUp/Down arrow - zoom in/out\n"
  127.         "\tl - cycle through texture lookup tables\n"
  128.         "\tw - cycle through warping effects\n"
  129.         "\tLeft mouse - drag image\n"
  130.         "\tMiddle/Right mouse - rotate image CCW/CW\n"
  131.         "\th/? - help\n"
  132.         "\tEsc - quit\n");
  133. }
  134.  
  135. void
  136. main(int argc, char **argv)
  137. {
  138.     GLXContext ctx;
  139.     int visualAttr[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 1, None};
  140.  
  141.     if (argc < 2)
  142.         usage(argv[0], EXIT_FAILURE);
  143.     if (argv[1][0] == '-' && argv[1][1] == 'h')
  144.         usage(argv[0], EXIT_SUCCESS);
  145.         
  146.     winxsize = winysize = 768;
  147.     createWindowAndContext(&dpy, &win, &ctx, 0, 0, winxsize, winysize,
  148.                            GL_TRUE, NULL, visualAttr, "lens");
  149.     /* Change the event mask to watch for motion and button release as well */
  150.     XSelectInput(dpy,win, ExposureMask | StructureNotifyMask | KeyPressMask |
  151.                  ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
  152.     XFlush(dpy);
  153.     glClear(GL_COLOR_BUFFER_BIT);
  154.     glXSwapBuffers(dpy, win);
  155.  
  156.     /*
  157.      *    check for required extensions.
  158.      *    we know an RE/REC/REV with "abgr" has limited "subtexture" support,
  159.      *    but doesn't advertise it.
  160.      */
  161.     if (!QueryExtension("GL_EXT_subtexture") &&
  162.     (strncmp("RE",glGetString(GL_RENDERER),2) ||
  163.          !QueryExtension("GL_EXT_abgr"))) {
  164.  
  165.     fprintf(stderr,"Sorry, EXT_subtexture required.. trying anyway.\n");
  166. #if 0
  167.     exit(EXIT_FAILURE);
  168. #endif
  169.     }
  170.  
  171. #if defined(GL_SGI_texture_color_table)
  172.     if (!(useTct = QueryExtension("GL_SGI_texture_color_table"))) {
  173.         /*
  174.          * HACK - texture color table may not be formally advertised.
  175.          * Try using it anyhow.
  176.          */
  177.     glDisable(GL_TEXTURE_COLOR_TABLE_SGI);
  178.         if (glGetError() == GL_NO_ERROR) {
  179.             fprintf(stderr, 
  180.          "Assuming SGI_texture_color_table supported but not advertised\n");
  181.             useTct = GL_TRUE;
  182.         }
  183.     } else
  184.         useTct = GL_TRUE;
  185.     if (!useTct)
  186.         fprintf(stderr,
  187.              "SGI_texture_color_table is not supported by this renderer\n");
  188. #else
  189.     useTct = GL_FALSE;
  190. #endif
  191.  
  192.     {
  193.         IMAGE *image = iopen(argv[1], "r");
  194.         int iclose(IMAGE *);
  195.         
  196.     if (!image) {
  197.         fprintf(stderr,"%s: can't open input file %s\n",argv[0], argv[1]);
  198.         exit(EXIT_FAILURE);
  199.     }
  200.     if (argc > 2) {
  201.             tileXSize = atoi(argv[2]);
  202.             tileYSize = argc > 3 ? atoi(argv[3]) : tileXSize;
  203.     }
  204.     fprintf(stderr,"TILE{XSIZE, YSIZE} = %d,%d\n",tileXSize,tileYSize);
  205.         img = readTiles(image, tileXSize, tileYSize);
  206.     (void) iclose(image);
  207.     }
  208.  
  209.     makeRgbaBgdTile();
  210.     applyRgbaBgd(img);
  211.  
  212.     glMatrixMode(GL_TEXTURE);
  213.     glLoadIdentity();
  214.     glTranslatef(0.5,0.5,0.0);
  215.     glScalef(.61,.61,1.);
  216.     glMatrixMode(GL_PROJECTION);
  217.     glLoadIdentity();
  218.     gluPerspective(90.,1.,.1,10.);
  219.     glMatrixMode(GL_MODELVIEW);
  220.     glLoadIdentity();
  221.     glTranslatef(0.,0.,-1.5);
  222.  
  223.     glEnable(GL_TEXTURE_2D);
  224.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  225.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  226.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); /*default*/
  227.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); /*default*/
  228.  
  229.     glTexImage2D(GL_TEXTURE_2D,0,GL_RGB5_EXT,TEX_SIZE_S,TEX_SIZE_T,0,
  230.                  GL_RGBA,GL_UNSIGNED_BYTE,NULL);
  231. #if DEBUG
  232.     chkError("after glTexImage2D");
  233. #endif
  234.  
  235.     xorg = -(img->xsize/2.0 - TEX_SIZE_S/2.0);
  236.     yorg = -(img->ysize/2.0 - TEX_SIZE_T/2.0);
  237.  
  238.     makeMesh0(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
  239.  
  240.     drawTiles(img,-xorg,-yorg,winxsize,winysize);
  241.     glXSwapBuffers(dpy, win);
  242.  
  243.     chkError("before processEvents");
  244.  
  245.     printHelp();
  246.  
  247.     processEvents();
  248. }
  249.  
  250. void
  251. usage(char *name, int exitStatus)
  252. {
  253.     fprintf(stderr,
  254.             "usage: %s [-h (for help)] inimage [[tileWidthAndHeight] or\
  255.  [tileWidth tileHeight]]\n", name);
  256.     fprintf(stderr,
  257.             "\tInteractively, `h/?' keys provide description of interface\n");
  258.     exit(exitStatus);
  259. }
  260.  
  261. void
  262. processEvents(void)
  263. {
  264.     int lx, ly, mx, my;
  265.     float fx, fy;
  266.     int i;
  267.     int leftdown = 0;
  268.  
  269.     while(1) {
  270.     int needredraw;
  271.     XEvent event;
  272.     XNextEvent(dpy, &event);
  273.     switch (event.type) {
  274.           case Expose: /* window needs to be redrawn */
  275.           {
  276.               /* skip all but last "Expose" event (X often sends 2 or 3) */
  277.               if (((XExposeEvent*) &event)->count == 0) {
  278.                   drawTiles(img,-xorg,-yorg,winxsize,winysize);
  279.                   glXSwapBuffers(dpy, win);
  280.               }
  281.           }
  282.           break;
  283.           case ConfigureNotify: /* window resize (or a move) occurred */
  284.           {
  285.               winxsize = ((XConfigureEvent*) &event)->width;
  286.               winysize = ((XConfigureEvent*)&event)->height;
  287.               glViewport(0, 0, winxsize, winysize);
  288.               drawTiles(img,-xorg,-yorg,winxsize,winysize);
  289.               glXSwapBuffers(dpy, win);
  290.           }
  291.           break;
  292.           case KeyPress:
  293.           {
  294.               KeySym keysym;
  295.  
  296.               (void) XLookupString(&event.xkey, NULL, 0, &keysym, 0);
  297.               switch (keysym) {
  298.                 case XK_Escape: /* ESC key */
  299.                   exit(EXIT_SUCCESS);
  300.                   break;
  301.                 case XK_Up: /* up arrow */
  302.                   zoom -= .02;
  303.                   if (zoom < 0.02) zoom = 0.02;
  304.                   drawTiles(img,-xorg,-yorg,winxsize,winysize); 
  305.                   glXSwapBuffers(dpy, win);
  306.                   break;
  307.                 case XK_Down: /* down arrow */
  308.                   zoom += .02;
  309.                   if (zoom > 1) zoom = 1;
  310.                   drawTiles(img,-xorg,-yorg,winxsize,winysize); 
  311.                   glXSwapBuffers(dpy, win);
  312.                   break;
  313.                 case XK_w:
  314.                   changeModel();
  315.                   drawTiles(img,-xorg,-yorg,winxsize,winysize); 
  316.                   glXSwapBuffers(dpy, win);
  317.                   break;
  318.                 case XK_l: /* left arrow */
  319.                   changeTct();
  320.                   chkError("after changeTct");
  321.                   drawTiles(img,-xorg,-yorg,winxsize,winysize); 
  322.                   glXSwapBuffers(dpy, win);
  323.                   break;
  324.                 case XK_h:
  325.                 case XK_H:
  326.                 case XK_question:
  327.           printHelp();
  328.                   break;
  329.               }
  330.           }
  331.                   break;
  332.           case ButtonPress:
  333.           {
  334.               switch (((XButtonEvent *)&event)->button) {
  335.                 case 1:
  336.                   leftdown = 1;
  337.                   lx = ((XButtonEvent *)&event)->x;
  338.                   ly = ((XButtonEvent *)&event)->y;
  339.           break;
  340.                 case 2:
  341.                   do {
  342.                       myangle -= 1.0;
  343.                       if (myangle < -360.0)
  344.                           myangle += 360.0;
  345.                       drawTiles(img, -xorg, -yorg, winxsize, winysize); 
  346.                       glXSwapBuffers(dpy, win);
  347.                   } while(xGetButton(2, dpy, win));
  348.                   break;
  349.                 case 3:
  350.                   do {
  351.                       myangle += 1.0;
  352.                       if (myangle > 360.0)
  353.                           myangle -= 360.0;
  354.                       drawTiles(img,-xorg,-yorg,winxsize,winysize); 
  355.                       glXSwapBuffers(dpy, win);
  356.                   } while (xGetButton(3, dpy, win));
  357.                   break;
  358.               }
  359.           }
  360.           break;
  361.  
  362.           case MotionNotify: /* cursor moved (in window) */
  363.         /* absorb extra motion events... */
  364.         if (leftdown) {
  365.         XMotionEvent *ev = (XMotionEvent*)&event;
  366.  
  367.         while (XEventsQueued(dpy, QueuedAfterReading)) {
  368.               XEvent tev;
  369.  
  370.               XNextEvent(dpy, &tev);
  371.               if (tev.type == MotionNotify) {
  372.               ev = (XMotionEvent*)&tev;
  373.               } else {
  374.               XPutBackEvent(dpy, &tev);
  375.               break;
  376.               }
  377.         }
  378.         mx = ev->x;
  379.         my = ev->y;
  380.         if(mx != lx || my != ly) {
  381.               xorg += (mx - lx);
  382.               yorg += -(my - ly); /* in X, y is inverted (yuk) */
  383.               drawTiles(img, -xorg, -yorg, winxsize, winysize);
  384.               glXSwapBuffers(dpy, win);
  385.               lx = mx;
  386.               ly = my;
  387.         }
  388.         }
  389.           break;
  390.       case ButtonRelease:
  391.         if (((XButtonEvent *)&event)->button == 1)
  392.         leftdown = 0;
  393.         break;
  394.     }
  395. #if DEBUG
  396.     chkError("processEvents");
  397. #endif
  398.     }
  399. }
  400.  
  401.  
  402. void
  403. changeModel(void)
  404. {
  405.     static int model = 0;
  406.  
  407.     model = (model + 1) % 4;
  408.     switch (model) {
  409.       case 0:  
  410.         makeMesh0(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
  411.         break;
  412.       case 1:  
  413.         makeMesh1(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
  414.         break;
  415.       case 2:  
  416.         makeMesh3(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
  417.         break;
  418.       case 3:  
  419.         makeMesh2(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
  420.         break;
  421.     }
  422. }
  423.  
  424. tileimg *
  425. readTiles(IMAGE *image, int tilexsize, int tileysize)
  426. {
  427.     int xsize, ysize, zsize;
  428.     int i, x, y, ntiles;
  429.     u_int32 *lptr;
  430.     u_int32 ***tiles;
  431.     tileimg *img;
  432.     unsigned short rbuf[MAXWIDTH];
  433.     unsigned short gbuf[MAXWIDTH];
  434.     unsigned short bbuf[MAXWIDTH];
  435.     u_int32 lbuf[MAXWIDTH];
  436.  
  437.  
  438.     xsize = image->xsize;
  439.     ysize = image->ysize;
  440.     zsize = image->zsize;
  441.  
  442.     if (image->xsize > MAXWIDTH) {
  443.     printf("cannot handle image wider than %d pixels.\n", MAXWIDTH);
  444.     exit(EXIT_FAILURE);
  445.     }
  446.  
  447.     img = (tileimg *) malloc(sizeof(tileimg));
  448.     img->xsize = xsize;
  449.     img->ysize = ysize;
  450.     img->xtiles = ((xsize-1)/tilexsize)+1;
  451.     img->ytiles = ((ysize-1)/tileysize)+1;
  452.     img->tilexsize = tilexsize;
  453.     img->tileysize = tileysize;
  454.     img->tiles =
  455.         (u_int32**) malloc(img->ytiles*img->xtiles * sizeof(u_int32*));
  456.     ntiles = img->xtiles*img->ytiles;
  457. #if DEBUG
  458.     printf("begin malloc ntile %d size %d\n",ntiles,tilexsize*tileysize*4);
  459.     printf("\t\t tilexsize,tileysize: %d %d xsize,ysize %d %d xtiles\
  460.  ytiles:%d %d\n", tilexsize,tileysize,xsize,ysize,img->xtiles,img->ytiles);
  461. #endif
  462.     for(i=0; i<ntiles; i++) {
  463.     img->tiles[i] =
  464.             (u_int32 *) malloc(tilexsize*tileysize*sizeof(u_int32));
  465.     }
  466. #if DEBUG
  467.     printf("end malloc\n");
  468. #endif
  469.     printf("Reading image..."); fflush(stdout);
  470.     for(y=0; y<ysize; y++) {
  471.         int getrow(IMAGE *image, unsigned short *buffer,
  472.                    unsigned int y, unsigned int z);
  473.         if(zsize >= 3) {
  474.         getrow(image,rbuf,y,0);
  475.         getrow(image,gbuf,y,1);
  476.         getrow(image,bbuf,y,2);
  477.         rgbToPackedRgba(rbuf,gbuf,bbuf,lbuf,xsize);
  478.     } else {
  479.         getrow(image,rbuf,y,0);
  480.         rgbToPackedRgba(rbuf,rbuf,rbuf,lbuf,xsize);
  481.     }
  482.     for(x=0; x<img->xtiles; x++) {
  483.         lptr = GETTILE(img,x,y/tileysize) + (tilexsize*(y%tileysize));
  484.         bcopy(lbuf+x*tilexsize,lptr,tilexsize*sizeof(u_int32));
  485.     }
  486.     }
  487.     printf("Done\n"); fflush(stdout);
  488.     return img;
  489. }
  490.  
  491. /*
  492.  * The following 4 procedures create meshes for the different kind of
  493.  * warping effects.
  494.  */
  495. #define MAXMESH 64
  496.  
  497. float Ml[4*2*(MAXMESH+1)*2 * (MAXMESH+1)];
  498.  
  499. void
  500. makeMesh0(float x0, float x1, float y0, float y1,
  501.           float s0, float s1, float t0, float t1, float z, int nx,int ny)
  502. {
  503.     float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
  504.     float v;
  505.     float *mp = Ml;
  506.     
  507.     dx = (x1-x0)/nx;
  508.     dy = (y1-y0)/ny;
  509.     ds = (s1-s0)/nx;
  510.     dt = (t1-t0)/ny;
  511.     y = y0;
  512.     t = t0;
  513.     vb[2] = z;
  514.     while (y < y1) {
  515.         x = x0;
  516.         s = s0;
  517.         while(x <= x1) {
  518.             tb[0] = s; tb[1] = t;
  519.             vb[0] = x; vb[1] = y;
  520.             vb[2] = 0.0;
  521.             *mp++ = tb[0];    
  522.             *mp++ = tb[1];    
  523.             mp += 2;
  524.             *mp++ = vb[0];    
  525.             *mp++ = vb[1];    
  526.             *mp++ = vb[2];    
  527.             mp++;
  528.             tb[1] = t+dt;
  529.             vb[1] = y+dy;
  530.             vb[2] = 0.0;
  531.             *mp++ = tb[0];    
  532.             *mp++ = tb[1];    
  533.             mp += 2;
  534.             *mp++ = vb[0];    
  535.             *mp++ = vb[1];    
  536.             *mp++ = vb[2];    
  537.             mp++;
  538.             x += dx;
  539.             s += ds;
  540.         }    
  541.         y += dy;
  542.         t += dt;
  543.     }
  544. }
  545.  
  546. void
  547. makeMesh1(float x0, float x1, float y0, float y1,
  548.           float s0, float s1, float t0, float t1, float z, int nx, int ny)
  549. {
  550.     float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
  551.     float v;
  552.     float *mp = Ml;
  553.     float N = 2.0;
  554.     float B = -1.5;
  555.     
  556.     dx = (x1-x0)/nx;
  557.     dy = (y1-y0)/ny;
  558.     ds = (s1-s0)/nx;
  559.     dt = (t1-t0)/ny;
  560.     y = y0;
  561.     t = t0;
  562.     vb[2] = z;
  563.     while (y < y1) {
  564.         x = x0;
  565.         s = s0;
  566.         while(x <= x1) {
  567.             tb[0] = s; tb[1] = t;
  568.             vb[0] = x; vb[1] = y;
  569.             v = N*N - x*x - y*y;
  570.             if (v < 0.0) v = 0.0;
  571.             vb[2] = sqrt(v) + B;
  572.             if (vb[2] < 0.) vb[2] = 0.0;
  573.             *mp++ = tb[0];    
  574.             *mp++ = tb[1];    
  575.             mp += 2;
  576.             *mp++ = vb[0];    
  577.             *mp++ = vb[1];    
  578.             *mp++ = vb[2];    
  579.             mp++;
  580.             tb[1] = t+dt;
  581.             vb[1] = y+dy;
  582.             v = N*N - x*x - (y+dy)*(y+dy);
  583.             if (v < 0.0) v = 0.0;
  584.             vb[2] = sqrt(v) + B;
  585.             if (vb[2] < 0.) vb[2] = 0.0;
  586.             *mp++ = tb[0];    
  587.             *mp++ = tb[1];    
  588.             mp += 2;
  589.             *mp++ = vb[0];    
  590.             *mp++ = vb[1];    
  591.             *mp++ = vb[2];    
  592.             mp++;
  593.             x += dx;
  594.             s += ds;
  595.         }    
  596.         y += dy;
  597.         t += dt;
  598.     }
  599. }
  600.  
  601. void
  602. makeMesh2(float x0, float x1, float y0, float y1,
  603.           float s0, float s1, float t0, float t1, float z, int nx,int ny)
  604. {
  605.     float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
  606.     float v;
  607.     float *mp = Ml;
  608.     float N2 = 4.0;
  609.     float B2 = -3.5;
  610.     
  611.     dx = (x1-x0)/nx;
  612.     dy = (y1-y0)/ny;
  613.     ds = (s1-s0)/nx;
  614.     dt = (t1-t0)/ny;
  615.     y = y0;
  616.     t = t0;
  617.     vb[2] = z;
  618.     while (y < y1) {
  619.         x = x0;
  620.         s = s0;
  621.         while(x <= x1) {
  622.             tb[0] = s; tb[1] = t;
  623.             vb[0] = x; vb[1] = y;
  624.             v = N2*N2 - x*x - y*y;
  625.             if (v < 0.0) v = 0.0;
  626.             vb[2] = sqrt(v) + B2;
  627.             *mp++ = tb[0];    
  628.             *mp++ = tb[1];    
  629.             mp += 2;
  630.             *mp++ = vb[0];    
  631.             *mp++ = vb[1];    
  632.             *mp++ = vb[2];    
  633.             mp++;
  634.             tb[1] = t+dt;
  635.             vb[1] = y+dy;
  636.             v = N2*N2 - x*x - (y+dy)*(y+dy);
  637.             if (v < 0.0) v = 0.0;
  638.             vb[2] = sqrt(v) + B2;
  639.             *mp++ = tb[0];    
  640.             *mp++ = tb[1];    
  641.             mp += 2;
  642.             *mp++ = vb[0];    
  643.             *mp++ = vb[1];    
  644.             *mp++ = vb[2];    
  645.             mp++;
  646.             x += dx;
  647.             s += ds;
  648.         }    
  649.         y += dy;
  650.         t += dt;
  651.     }
  652. }
  653.  
  654. void
  655. makeMesh3(float x0, float x1, float y0, float y1,
  656.           float s0, float s1, float t0, float t1, float z, int nx, int ny)
  657. {
  658.     float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
  659.     float v;
  660.     float *mp = Ml;
  661.     float N3 = 2.0;
  662.     float B3 = -1.0;
  663.     
  664.     dx = (x1-x0)/nx;
  665.     dy = (y1-y0)/ny;
  666.     ds = (s1-s0)/nx;
  667.     dt = (t1-t0)/ny;
  668.     y = y0;
  669.     t = t0;
  670.     vb[2] = z;
  671.     while (y < y1) {
  672.         x = x0;
  673.         s = s0;
  674.         while(x <= x1) {
  675.             tb[0] = s; tb[1] = t;
  676.             vb[0] = x; vb[1] = y;
  677.             v = N3*N3 - x*x - y*y;
  678.             if (v < 0.0) v = 0.0;
  679.             vb[2] = sqrt(v) + B3;
  680.             if (vb[2] < 0.) vb[2] = 0.0;
  681.             vb[2] = -vb[2];
  682.             *mp++ = tb[0];    
  683.             *mp++ = tb[1];    
  684.             mp += 2;
  685.             *mp++ = vb[0];    
  686.             *mp++ = vb[1];    
  687.             *mp++ = vb[2];    
  688.             mp++;
  689.             tb[1] = t+dt;
  690.             vb[1] = y+dy;
  691.             v = N3*N3 - x*x - (y+dy)*(y+dy);
  692.             if (v < 0.0) v = 0.0;
  693.             vb[2] = sqrt(v) + B3;
  694.             if (vb[2] < 0.) vb[2] = 0.0;
  695.             vb[2] = -vb[2];
  696.             *mp++ = tb[0];    
  697.             *mp++ = tb[1];    
  698.             mp += 2;
  699.             *mp++ = vb[0];    
  700.             *mp++ = vb[1];    
  701.             *mp++ = vb[2];    
  702.             mp++;
  703.             x += dx;
  704.             s += ds;
  705.         }    
  706.         y += dy;
  707.         t += dt;
  708.     }
  709. }
  710.  
  711. void
  712. drawMesh(int nx,int ny)
  713. {
  714.     float *mp = Ml;
  715.     int i,j;
  716.  
  717.     glColor4f(1,1,1,1);
  718.     for (i = ny+1; i; i--) {
  719.         glBegin(GL_TRIANGLE_STRIP);
  720.         for (j = nx+1; j; j--) {
  721.             glTexCoord2fv(mp);    mp += 4;
  722.             glVertex3fv(mp);    mp += 4;
  723.             glTexCoord2fv(mp);    mp += 4;
  724.             glVertex3fv(mp);    mp += 4;
  725.         }
  726.         glEnd();
  727.     }
  728. }
  729.  
  730.  
  731. void
  732. loadtile(float s, float t, int x, int y, tileimg *img)
  733. {
  734.     GLvoid *tile;
  735.  
  736.     tile = (GLvoid *) (x < 0 || x >= img->xtiles || y < 0 || y >= img->ytiles ?
  737.                        bgdtile : GETTILE(img,x,y));
  738.     glTexSubImage2DEXT(GL_TEXTURE_2D, 0, s*TEX_SIZE_S+.5, t*TEX_SIZE_T+.5,
  739.                        tileXSize, tileYSize, GL_RGBA, GL_UNSIGNED_BYTE,
  740.                        tile);
  741. #if DEBUG
  742.     chkError("after glTexSubImage2D");
  743. #endif
  744. }
  745.  
  746. void
  747. drawTiles(tileimg *img, int xorg, int yorg, int winxsize, int winysize)
  748. {
  749.     int minx,maxx,miny,maxy;
  750.     float s0,t0;
  751.     int x, y, first,last;
  752.  
  753.     glClear(GL_COLOR_BUFFER_BIT);
  754.  
  755.     minx = xorg < 0 ? (xorg - img->tilexsize - 1)/img->tilexsize :
  756.         xorg/img->tilexsize;
  757.     maxx = (xorg + TEX_SIZE_S)/(float) img->tilexsize - 1;
  758.     miny = yorg < 0 ? (yorg-img->tileysize-1)/img->tileysize :
  759.         yorg/img->tileysize;
  760.     maxy = (yorg + TEX_SIZE_T)/(float) img->tileysize - 1;
  761.  
  762.     /* Bring in any newly exposed tiles on the left */
  763.     if (minx < Lminx) {
  764.         for (x = minx; x < Lminx; x++) {
  765.         s0 = x * (tileXSize/(float) TEX_SIZE_S);
  766.         s0 -= (int) s0;  /* get the fractional position */
  767.          if (s0 < 0.0)
  768.         s0 += 1.0;
  769.         for (y = miny; y <= maxy; y++) {
  770.         t0 = y * (tileYSize/(float) TEX_SIZE_T);
  771.         t0 -= (int) t0;
  772.              if (t0 < 0.0)
  773.             t0 += 1.0;
  774.                 loadtile(s0, t0, x, y, img);
  775.         
  776.         }
  777.     }
  778.     first = Lminx;
  779.     } else
  780.         first = minx;
  781.  
  782.     /* Bring in newly exposed tiles on the right */
  783.     if (maxx > Lmaxx) {
  784.     x = Lmaxx > minx ? Lmaxx+1 : minx;
  785.      last = x - 1;
  786.         for (; x <= maxx; x++) {
  787.         s0 = x * (tileXSize/(float) TEX_SIZE_S);
  788.         s0 -= (int) s0;  /* get the fractional position */
  789.          if (s0 < 0.0)
  790.         s0 += 1.0;
  791.         for (y = miny; y <= maxy; y++) {
  792.         t0 = y * (tileYSize/(float) TEX_SIZE_T);
  793.         t0 -= (int) t0;
  794.              if (t0 < 0.0)
  795.             t0 += 1.0;
  796.                 loadtile(s0, t0, x, y, img);
  797.         }
  798.     }
  799.     } else
  800.         last = maxx;
  801.  
  802.     /* Bring in newly exposed tiles on the bottom */
  803.     if (miny < Lminy) {
  804.         for (y = miny; y < Lminy; y++) {
  805.         t0 = y * (tileYSize/(float) TEX_SIZE_T);
  806.         t0 -= (int) t0;  /* get the fractional position */
  807.          if (t0 < 0.0)
  808.         t0 += 1.0;
  809.         for (x = first; x <= last; x++) {
  810.         s0 = x * (tileXSize/(float) TEX_SIZE_S);
  811.                 s0 -= (int) s0;  /* get the fractional position */
  812.              if (s0 < 0.0)
  813.             s0 += 1.0;
  814.                 loadtile(s0, t0, x, y, img);
  815.         }
  816.     }
  817.     }
  818.  
  819.     /* Bring in newly exposed tiles on the top */
  820.     if (maxy > Lmaxy) {
  821.         for (y = Lmaxy+1 ; y <= maxy; y++) {
  822.         t0 = y * (tileYSize/(float) TEX_SIZE_T);
  823.         t0 -= (int) t0;  /* get the fractional position */
  824.          if (t0 < 0.0)
  825.         t0 += 1.0;
  826.         for (x = first; x <= last; x++) {
  827.         s0 = x * (tileXSize/(float) TEX_SIZE_S);
  828.                 s0 -= (int) s0;  /* get the fractional position */
  829.              if (s0 < 0.0)
  830.             s0 += 1.0;
  831.                 loadtile(s0, t0, x, y, img);
  832.         }
  833.     }
  834.     }
  835.  
  836.     Lminx = minx;
  837.     Lmaxx = maxx;
  838.     Lminy = miny;
  839.     Lmaxy = maxy;
  840.     glMatrixMode(GL_TEXTURE);
  841.     glLoadIdentity();
  842.     glTranslatef(xorg/(float) TEX_SIZE_S+0.5,yorg/(float) TEX_SIZE_T+0.5,0.0);
  843.     glRotatef(myangle, 0, 0, 1); /* z rotate */
  844.     glScalef(.63*zoom,.63*zoom,1.);
  845.     glTranslatef(-.5,-.5,0.);
  846.     glMatrixMode(GL_MODELVIEW);
  847.  
  848.     drawMesh(64,64);
  849. }
  850.  
  851.  
  852. void
  853. changeTct(void)
  854. {
  855.     static int lut = 0;
  856.  
  857.     if (!useTct) {
  858.         fprintf(stderr, "SGI_texture_color_table is not supported\n");
  859.         return;
  860.     }
  861.     
  862. #if defined(GL_SGI_texture_color_table)
  863.  
  864.     lut = (lut + 1) % 5;
  865.     if (lut == 0) {
  866.     glDisable(GL_TEXTURE_COLOR_TABLE_SGI);
  867.         chkError("after disable TCT");
  868.         return;
  869.     }
  870.     glEnable(GL_TEXTURE_COLOR_TABLE_SGI);
  871.     chkError("after enable TCT");
  872.  
  873.     switch (lut) {
  874.     case 1: makeTable1(); break;
  875.     case 2: makeTable2(); break;
  876.     case 3: makeTable3(); break;
  877.     case 4: makeTable4(); break;
  878.     }
  879. #endif
  880. }
  881.  
  882. void
  883. makeTable1(void)
  884. {    
  885. #if defined(GL_SGI_texture_color_table)
  886.     static unsigned long table[256];
  887.     static int done = 0;
  888.     int i;
  889.     float v;
  890.     int iv;
  891.  
  892.     if (!done) {
  893.     for (i = 0; i < 256; i++){
  894.         v = i/255.0;
  895.         iv = powf(v,(float) 2.0) * 255;
  896.         table[i] = ((iv)<<24) | ((iv)<<16) | ((iv)<<8) | ((iv)); 
  897.     }
  898.     done = 1;
  899.     }
  900.  
  901.     glColorTableSGI(GL_TEXTURE_COLOR_TABLE_SGI, GL_RGBA8_EXT, 256,
  902.                     GL_RGBA, GL_UNSIGNED_BYTE, table);
  903. #endif
  904. }
  905.  
  906. void
  907. makeTable2(void)
  908. {    
  909. #if defined(GL_SGI_texture_color_table)
  910.     static unsigned long table[256];
  911.     static int done = 0;
  912.     int i;
  913.     float v;
  914.     int iv;
  915.  
  916.     if (!done) {
  917.     for (i = 0; i < 256; i++) {
  918.         v = i/255.0;
  919.         iv = powf(v,(float) 1.0) * 255;
  920.         table[i] = ((iv)<<24) | ((iv)<<16) | ((iv)<<8) | ((iv));
  921.     }
  922.     done = 1;
  923.     }
  924.  
  925.     glColorTableSGI(GL_TEXTURE_COLOR_TABLE_SGI, GL_RGBA8_EXT, 256,
  926.                     GL_RGBA, GL_UNSIGNED_BYTE, table);
  927. #endif
  928. }
  929.  
  930.  
  931. /*
  932.  *  define DLIST first time, and call it every time.
  933.  */
  934. void
  935. makeTable3(void)
  936. {    
  937. #if defined(GL_SGI_texture_color_table)
  938.     static unsigned long table[256];
  939.     static GLuint list = 0;
  940.     int i;
  941.     float v;
  942.     int iv;
  943.  
  944.     if (list == 0) {
  945.     for (i = 0; i < 256; i++){
  946.         v = i/255.0;
  947.         iv = powf(v,(float) 0.5) * 255;
  948.         table[i] = ((iv)<<24) | ((iv)<<16) | ((iv)<<8) | ((iv)); 
  949.     }
  950.         list = glGenLists(1);
  951.     glNewList(list, GL_COMPILE);
  952.     glColorTableSGI(GL_TEXTURE_COLOR_TABLE_SGI, GL_RGBA8_EXT, 256,
  953.                         GL_RGBA, GL_UNSIGNED_BYTE, table);
  954.     glEndList();
  955.     }
  956.  
  957.     glCallList(list);
  958. #endif
  959. }
  960.  
  961. /*
  962.  *  Create an inverting color table ("negative" effect)
  963.  *  use LUMINANCE table because R,G,B,A tables are the same.
  964.  */
  965. void
  966. makeTable4(void)
  967. {    
  968. #if defined(GL_SGI_texture_color_table)
  969.     static unsigned char table[256];
  970.     static int done = 0;
  971.     int i;
  972.  
  973.     if (!done) {
  974.     for (i = 0; i < 256; i++) {
  975.         table[i] = 255-i; 
  976.     }
  977.     done = 1;
  978.     }
  979.     glColorTableSGI(GL_TEXTURE_COLOR_TABLE_SGI, GL_RGBA8_EXT, 256,
  980.                     GL_LUMINANCE, GL_UNSIGNED_BYTE, table);
  981. #endif
  982. }
  983.  
  984. void
  985. rgbToPackedRgba(unsigned short *rbuf, unsigned short *gbuf,
  986.                 unsigned short *bbuf, u_int32 *lbuf, int xsize)
  987. {
  988.     char *cptr;    
  989.     int i;
  990.     
  991.     cptr = (char *) lbuf;
  992.  
  993.     for (i = xsize; i; i--) {
  994.         *cptr++ = *rbuf++;
  995.         *cptr++ = *gbuf++;
  996.         *cptr++ = *bbuf++;
  997.         *cptr++ = 0x00;
  998.     }
  999. }
  1000.  
  1001. /*
  1002.  * "Draw" an rgb tile for the background.
  1003.  */
  1004. void
  1005. makeRgbBgdTile(void)
  1006. {
  1007.     int i,j,grid;
  1008.     char *ptr;
  1009.  
  1010.     bgdtile = (u_int32 *) malloc(tileXSize*tileYSize*sizeof(u_int32)*3/4);
  1011.     grid = 8;
  1012.     ptr = (char *) bgdtile;
  1013.     for (i=0; i<tileYSize; i++) {
  1014.     for(j=0; j<tileXSize; j++) {
  1015.        if(i%grid == 0 || j%grid == 0) {
  1016.         *ptr++ = 0x0; *ptr++ = 0x0; *ptr++ = 0x40; 
  1017.        } else {
  1018.         *ptr++ = 0x40; *ptr++ = 0x40; *ptr++ = 0x40; 
  1019.        }
  1020.         }
  1021.     }
  1022. }
  1023.  
  1024. /*
  1025.  * "Draw" an rgba tile for the background.
  1026.  */
  1027. void
  1028. makeRgbaBgdTile(void)
  1029. {
  1030.     int i,j,grid;
  1031.     u_int32 *ptr;
  1032.  
  1033.     bgdtile = (u_int32 *) malloc(tileXSize*tileYSize*sizeof(u_int32));
  1034.     grid = 8;
  1035.     ptr = (u_int32 *) bgdtile;
  1036.     for (i=0; i<tileYSize; i++) {
  1037.     for(j=0; j<tileXSize; j++) {
  1038.        if(i%grid == 0 || j%grid == 0) {
  1039.         *ptr++ = 0x40000000;    /* red is the upper byte */
  1040.        } else {
  1041.         *ptr++ = 0x40404000;
  1042.        }
  1043.         }
  1044.     }
  1045. }
  1046.  
  1047. void
  1048. applyBgd(tileimg *img)
  1049. {
  1050.     int extras,y,x,i,j;
  1051.     char *ptr,*bgd;
  1052.  
  1053.     extras = img->xsize % img->tilexsize;
  1054.     if (extras) {
  1055.     for (y=0; y< img->ytiles; y++) {
  1056.         ptr = (char *) GETTILE(img,img->xtiles-1,y);
  1057.         bgd = (char *) bgdtile;
  1058.         for (j = 0; j< img->tileysize; j++) {
  1059.         ptr += 3*extras;        
  1060.         bgd += 3*extras;        
  1061.         for (i=extras; i< img->tilexsize; i++) {
  1062.             *ptr++ = *bgd++;        
  1063.             *ptr++ = *bgd++;        
  1064.             *ptr++ = *bgd++;        
  1065.         }
  1066.         }
  1067.     }
  1068.     }
  1069.     extras = img->ysize % img->tileysize;
  1070.     if (extras) {
  1071.     for (x=0; x< img->xtiles; x++) {
  1072.         ptr = (char *) GETTILE(img,x,img->ytiles-1);
  1073.         bgd = (char *) bgdtile;
  1074.         ptr += 3*extras* img->tilexsize;
  1075.         bgd += 3*extras* img->tilexsize;
  1076.         for (j = extras; j< img->tileysize; j++) {
  1077.         for (i=0; i< img->tilexsize; i++) {
  1078.             *ptr++ = *bgd++;        
  1079.             *ptr++ = *bgd++;        
  1080.             *ptr++ = *bgd++;        
  1081.         }
  1082.         }
  1083.     }
  1084.     }
  1085. }
  1086.  
  1087. void
  1088. applyRgbaBgd(tileimg *img)
  1089. {
  1090.     int extras,y,x,i,j;
  1091.     char *ptr,*bgd;
  1092.  
  1093.     extras = img->xsize % img->tilexsize;
  1094.     if (extras) {
  1095.     for (y=0; y< img->ytiles; y++) {
  1096.         ptr = (char *) GETTILE(img,img->xtiles-1,y);
  1097.         bgd = (char *) bgdtile;
  1098.         for (j = 0; j< img->tileysize; j++) {
  1099.         ptr += 4*extras;        
  1100.         bgd += 4*extras;        
  1101.         for (i=extras; i< img->tilexsize; i++) {
  1102.             *ptr++ = *bgd++;        
  1103.             *ptr++ = *bgd++;        
  1104.             *ptr++ = *bgd++;        
  1105.             *ptr++ = *bgd++;        
  1106.         }
  1107.         }
  1108.     }
  1109.     }
  1110.     extras = img->ysize % img->tileysize;
  1111.     if (extras) {
  1112.     for (x=0; x< img->xtiles; x++) {
  1113.         ptr = (char *) GETTILE(img,x,img->ytiles-1);
  1114.         bgd = (char *) bgdtile;
  1115.         ptr += 4*extras* img->tilexsize;
  1116.         bgd += 4*extras* img->tilexsize;
  1117.         for (j = extras; j< img->tileysize; j++) {
  1118.         for (i=0; i< img->tilexsize; i++) {
  1119.             *ptr++ = *bgd++;        
  1120.             *ptr++ = *bgd++;        
  1121.             *ptr++ = *bgd++;        
  1122.             *ptr++ = *bgd++;        
  1123.         }
  1124.         }
  1125.     }
  1126.     }
  1127. }
  1128.  
  1129. #if DEBUG
  1130. void
  1131. chkError(char *msg)
  1132. {
  1133.     GLenum err;
  1134.     char *errstr;
  1135.  
  1136.     while ((err = glGetError()) != GL_NO_ERROR) {
  1137.     fprintf(stderr, 
  1138.         "ERROR: %s: glGetError returned %s (expected GL_NO_ERROR)\n",
  1139.                 msg, gluErrorString(err));
  1140.     }
  1141. }
  1142. #endif
  1143. #endif /* defined on extensions (else part) */
  1144.